package com.ucode.sys.service.impl;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ucode.sys.mapper.DeptMapper;
import com.ucode.sys.model.Dept;
import com.ucode.sys.service.DeptService;
import com.ucode.sys.vo.DeptTreeNode;
import com.ucode.tool.tree.ForestNodeMerger;
import com.ucode.tool.util.IdentifyUtils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

@Service
public class DeptServiceImpl implements DeptService {

    private static Log log = LogFactory.get(DeptServiceImpl.class);
    @Autowired
    private DeptMapper deptMapper;
    
    @Override
    public Dept insert(Dept dept) {
        Long id = IdentifyUtils.getDefaultSnowflakeId();
        dept.setId(id);
        Date now = new Date();
        dept.setCreatedTime(now);
        dept.setUpdatedTime(now);
        if(dept.getParentId() == null){
          dept.setParentId(0L);
        }
        String ancestors = "0";
        if(!dept.getParentId().equals(0L)){
            Dept parent = deptMapper.findById(dept.getParentId());
            ancestors = StrUtil.concat(true,parent.getAncestors(), "," ,parent.getId().toString());
        }
        dept.setAncestors(ancestors);
        int i = deptMapper.insert(dept);
        return i > 0 ? dept : null;
    }

    @Override
    @Transactional
    public int update(Dept dept) {
        if(dept.getParentId() == null){
           dept.setParentId(0L);
        }
        int i = 0;
        Dept old = deptMapper.findById(dept.getId());
        if(old != null){
           if(!old.getParentId().equals(dept.getParentId())){
               String newAncestors = "0";
               if(!dept.getParentId().equals(0L)){
                   Dept parent = deptMapper.findById(dept.getParentId());
                   newAncestors = StrUtil.concat(true,parent.getAncestors(), "," ,parent.getId().toString());
               }
               dept.setAncestors(newAncestors);
               i = deptMapper.update(dept);
               if(i > 0){
                   //更新下级部门
                   String newAncestorsPrefix = StrUtil.concat(true,newAncestors, "," ,dept.getId().toString());
                   String oldAncestorsPrefix = StrUtil.concat(true,old.getAncestors(), "," ,old.getId().toString());
                   List<Long> childs = deptMapper.findAllChildsByAPL(oldAncestorsPrefix);
                   if(CollUtil.isNotEmpty(childs)){
                       List<Dept> childDepts = deptMapper.findByIds(childs);
                       for(Dept childDept : childDepts){
                           childDept.setAncestors(childDept.getAncestors().replace(oldAncestorsPrefix, newAncestorsPrefix));
                       }
                       deptMapper.updateAncestors(childDepts);
                   }
               }
           }
        }
        
        return i;
    }
    
    @Override
    public int delete(Long id) {
        return deptMapper.deleteById(id);
    }

    @Override
    public Dept findById(Long id) {
        return deptMapper.findById(id);
    }
    
    @Override
    public List<Dept> findByIds(List<Long> ids) {
        return deptMapper.findByIds(ids);
    }

    @Override
    public List<DeptTreeNode> findTree() {
        long startTime = DateUtil.current(false);
        List<DeptTreeNode> nodes = deptMapper.findAllTreeNodes();
        List<DeptTreeNode> trees = ForestNodeMerger.merge(nodes);
        long endTime = DateUtil.current(false);
        log.debug("查询部门树结构耗时:{}",(endTime-startTime));
        return trees;
    }
    
    @Override
    public int findDirectChildCount(Long id) {
        return deptMapper.findDirectChildCount(id);
    }

    @Override
    public List<Dept> findDirectChilds(Long id) {
        return deptMapper.findDirectChilds(id);
    }

    @Override
    public List<Long> findAllChilds(Long id) {
        Dept dept = deptMapper.findById(id);
        if(dept != null){
            String ancestorsPrefix = StrUtil.concat(true,dept.getAncestors(), "," ,dept.getId().toString(),"%");
            return deptMapper.findAllChildsByAPL(ancestorsPrefix);
        }
        return null;
    }

}
